package com.fuelindustries.ant.tasks;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Writer;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

public class BuildNumberCommand extends Task 
{
	private String _path;
	private String __revisionnumber;
	private String CLASS_NAME = "BuildNumber.as";
	
	public void execute() throws BuildException
	{		
		try
		{
			getBuildNumber();
			injectBuildNumber();
			trace( "BUILDING " + __revisionnumber );
		}
		catch( Exception e )
		{
			trace( e.getMessage() );
		}		
	}
	
	private void getBuildNumber() throws IOException, InterruptedException, BuildException
	{
		String[] command = new String[]{ "svnversion", "-n" };
		Process result = Runtime.getRuntime().exec(command);
        result.waitFor();
        
        String line;
        StringBuffer output = new StringBuffer();

        /* if something bad happened while trying to run the script, throw an AppleScriptException 
           letting the user know what the problem was */
        
        if (result.exitValue() != 0) 
        {
           
          // read in the description of the error
           BufferedReader err = new BufferedReader(new InputStreamReader( result.getErrorStream() ) );
           
           while( ( line = err.readLine() ) != null ) 
           {
               output.append(line + "\n");
           }
           trace( "ERROR " + output.toString().trim() );
           err.close();
           
           throw new BuildException( "Build Error getting the revision number" );
                 
        // otherwise the script ran successfully
        } 
        else 
        {

           /* read in the output */
           BufferedReader out = new BufferedReader(new InputStreamReader(result.getInputStream()));
           
           while ((line = out.readLine()) != null) 
           {
              output.append(line + "\n");
           }
                      
           String org = output.toString();
           
           if( org.indexOf( ":" ) != -1 )
           {
        	   String[] split = org.split( ":" );
        	   
        	   String n1 = split[ 0 ].replaceAll("\\D", "" ).trim();
        	   String n2 = split[ 1 ].replaceAll("\\D", "" ).trim();
        	   
        	   int i1 = Integer.valueOf( n1 ).intValue();
        	   int i2 = Integer.valueOf( n2 ).intValue();
        	   
               __revisionnumber = ( i1 > i2 ) ? n1 : n2; 
           }
           else
           {
        	   __revisionnumber = org.replaceAll("\\D", "" ).trim();
           }
           
           

           out.close();
        }
        
        result.destroy();
	}
	
	private void injectBuildNumber() throws IOException
	{
		File f = new File(_path + File.separator + CLASS_NAME );
		String classcontents = getContents( f );
		String newfile = classcontents.replaceAll("BUILD_NUMBER : String = \"[a-zA-Z_0-9]*\";", "BUILD_NUMBER : String = \"" + __revisionnumber + "\";" );
		setContents( f, newfile );
	}
	
	private void setContents(File aFile, String aContents) throws FileNotFoundException, IOException 
	{
		if (aFile == null) 
		{
			throw new IllegalArgumentException("File should not be null.");
		}
		
		if (!aFile.exists()) 
		{
			throw new FileNotFoundException ("File does not exist: " + aFile);
		}
		
		if (!aFile.isFile()) 
		{
			throw new IllegalArgumentException("Should not be a directory: " + aFile);
		}
		
		if (!aFile.canWrite()) 
		{
			throw new IllegalArgumentException("File cannot be written: " + aFile);
		}
		
		//use buffering
		Writer output = new BufferedWriter(new FileWriter(aFile));
		try 
		{
			//FileWriter always assumes default encoding is OK!
			output.write( aContents );
		}
		finally 
		{
			output.close();
		}
	}

	
	 private String getContents(File aFile) 
	 {
	    StringBuilder contents = new StringBuilder();
	    
	    try {
	      //use buffering, reading one line at a time
	      //FileReader always assumes default encoding is OK!
	      BufferedReader input =  new BufferedReader(new FileReader(aFile));
	      try {
	        String line = null; //not declared within while loop
	        /*
	        * readLine is a bit quirky :
	        * it returns the content of a line MINUS the newline.
	        * it returns null only for the END of the stream.
	        * it returns an empty String if two newlines appear in a row.
	        */
	        while (( line = input.readLine()) != null){
	          contents.append(line);
	          contents.append(System.getProperty("line.separator"));
	        }
	      }
	      finally {
	        input.close();
	      }
	    }
	    catch (IOException ex){
	      ex.printStackTrace();
	    }
	    
	    return contents.toString();
	}

	
	public void setPath(String x)
	{
		_path = x;
	}
	
	private void trace( String msg )
	{
		System.out.println( msg );
	}
}